package org.naive.vstream.render;

public class RendererState {
	private AbstractRenderer context;

	private int currentX;

	private int currentY;

	private int currentW;

	private int currentH;

	private int skipped;

	public RendererState(int x, int y, int w, int h) {
		currentX = x;
		currentY = y;
		currentW = w;
		currentH = h;
	}

	public void handleBit(boolean bit) {
		if (bit) {
			handleEnter();
		}
		else {
			handleSkip();
		}
	}

	protected void handleEnter() {
		skipped = 0;

		if (!canInRect()) {
			resign(new SubpixelRenderState());
		}
		else {
			inRect(getQuadStack().getHead());
			getQuadStack().push();
		}
	}

	protected void handleSkip() {
		if (++skipped >= 4) {
			skipped = 0;
			resign(new DirectValueState());
		}
		else {
			pop();
		}
	}

	private void pop() {
		while (!getQuadStack().isEmpty()) {
			if (!getQuadStack().getHead().canIncrement()) {
				getQuadStack().pop();
				skipped = 0;
				final Quad newHead = getQuadStack().getHead();
				if (newHead != null) {
					outRect(newHead);
				}
			}
			else {
				getQuadStack().incrementHead();
				break;
			}
		}
	}

	public void activate(AbstractRenderer context, RendererState prevState) {
		assert this.context == null;
		this.context = context;
		if (prevState instanceof SubpixelRenderState) {
			subpixelIsBack((SubpixelRenderState) prevState);
		}
		if (prevState instanceof DirectValueState) {
			directValueIsBack((DirectValueState) prevState);
		}
	}

	private void subpixelIsBack(SubpixelRenderState state) {

	}

	private void directValueIsBack(DirectValueState state) {
		fill(state.value());
		pop();
	}

	public void deactivate(AbstractRenderer context) {
		assert this.context == context;
		this.context = null;
	}

	protected void resign(RendererState successor) {
		context.scheduleState(successor);
	}

	protected void done() {
		context.scheduleDone();
	}

	protected QuadTreeStack getQuadStack() {
		return context.getQuadStack();
	}

	protected boolean canInRect() {
		return currentW >= 2 && currentH >= 2;
	}

	protected void fill(int brightness) {
		fill(currentX, currentY, currentW, currentH, brightness);
	}

	protected void fill(Quad q, int brightness) {
		inRect(q);
		fill(brightness);
		outRect(q);
	}

	protected void fill(int x, int y, int w, int h, int b) {
		context.outRect(x, y, w, h, b);
	}

	protected void inRect(Quad slotIndex) {
		assert currentW >= 2;
		assert currentH >= 2;

		currentW >>= 1;
		currentH >>= 1;
		if (slotIndex.isBotton()) {
			currentY += currentH;
		}
		if (slotIndex.isRight()) {
			currentX += currentW;
		}
	}

	protected void outRect(Quad slotIndex) {
		if (slotIndex.isBotton()) {
			currentY -= currentH;
		}
		if (slotIndex.isRight()) {
			currentX -= currentW;
		}
		currentH <<= 1;
		currentW <<= 1;

	}
}
